#pragma once

#include <iostream>
#include <vector>
#include <atomic>

#include "macros.h"

/**
 * @namespace Common
 * @brief 包含系统中共用的基础组件和工具类
 */
namespace Common {
  /**
   * @class LFQueue
   * @brief 无锁先进先出队列实现
   * 
   * 这是一个基于原子操作的无锁队列实现，用于在不同线程间安全地传递数据。
   * 它使用原子操作而非互斥锁，以提高并发性能。
   * 该队列在系统中用于传递客户端请求、客户端响应和市场数据更新等。
   * 
   * @tparam T 队列中存储的元素类型
   */
  template<typename T>
  class LFQueue final {
  public:
    /**
     * @brief 构造函数，初始化指定大小的队列
     * 
     * @param num_elems 队列的容量（元素数量）
     * 
     * @note 队列在创建时预分配所有存储空间，以避免运行时的内存分配
     */
    explicit LFQueue(std::size_t num_elems) :
        store_(num_elems, T()) /* pre-allocation of vector storage. */ {
    }

    /**
     * @brief 获取下一个可写入位置的指针
     * 
     * @return 指向下一个写入位置的指针
     * 
     * @note 这个函数仅返回指针，不更新写入索引，需要配合updateWriteIndex()使用
     */
    auto getNextToWriteTo() noexcept {
      return &store_[next_write_index_];
    }

    /**
     * @brief 更新写入索引并增加元素计数
     * 
     * 在写入数据后调用此函数更新写入位置和元素计数
     * 
     * @note 写入索引会在到达容器大小时循环回到开始位置
     */
    auto updateWriteIndex() noexcept {
      next_write_index_ = (next_write_index_ + 1) % store_.size();
      num_elements_++;
    }

    /**
     * @brief 获取下一个可读取元素的指针
     * 
     * @return 指向下一个读取元素的指针，如果队列为空则返回nullptr
     * 
     * @note 这个函数仅返回指针，不更新读取索引，需要配合updateReadIndex()使用
     */
    auto getNextToRead() const noexcept -> const T * {
      return (size() ? &store_[next_read_index_] : nullptr);
    }

    /**
     * @brief 更新读取索引并减少元素计数
     * 
     * 在读取数据后调用此函数更新读取位置和元素计数
     * 
     * @note 读取索引会在到达容器大小时循环回到开始位置
     * @note 如果队列为空但尝试读取，将触发断言失败
     */
    auto updateReadIndex() noexcept {
      next_read_index_ = (next_read_index_ + 1) % store_.size(); // wrap around at the end of container size.
      ASSERT(num_elements_ != 0, "Read an invalid element in:" + std::to_string(pthread_self()));
      num_elements_--;
    }

    /**
     * @brief 获取队列中当前的元素数量
     * 
     * @return 队列中当前的元素数量
     * 
     * @note 使用原子加载操作确保线程安全
     */
    auto size() const noexcept {
      return num_elements_.load();
    }

    /**
     * @brief 删除的默认构造函数、拷贝构造函数、移动构造函数和赋值运算符
     * 
     * 禁止默认构造、拷贝和移动操作，确保队列对象的完整性和线程安全
     */
    LFQueue() = delete;

    LFQueue(const LFQueue &) = delete;

    LFQueue(const LFQueue &&) = delete;

    LFQueue &operator=(const LFQueue &) = delete;

    LFQueue &operator=(const LFQueue &&) = delete;

  private:
    /**
     * @brief 存储数据的底层容器，以FIFO（先进先出）方式访问
     * 
     * 在创建时预分配存储空间，以避免运行时的内存分配
     */
    std::vector<T> store_;

    /**
     * @brief 原子类型的索引跟踪器，用于跟踪下一个写入和读取位置
     * 
     * 使用原子类型确保在多线程环境中的线程安全性
     */
    std::atomic<size_t> next_write_index_ = {0}; ///< 下一个写入位置的索引
    std::atomic<size_t> next_read_index_ = {0};  ///< 下一个读取位置的索引

    /**
     * @brief 当前队列中的元素数量
     * 
     * 使用原子类型确保在多线程环境中的线程安全性
     */
    std::atomic<size_t> num_elements_ = {0};
  };
}
